﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.ComponentModel;
using SPMS.Utility;
using SPMS.Commons.Configuration;
using SPMS.Log.Core;
using SPMS.Log.Utility;
using SPMS.Log.Configuration;
using SPMS.Log.Appender;

namespace SPMS.Log.Repository
{
    /// <summary>
    /// 日志存储器
    /// </summary>
    /// <remarks>默认的日志存储器实现</remarks>
    /// <history>
    /// [zanezeng]               2009/10/14 9:46    创建
    /// </history>
    public class LoggingRepository : IConfigurableLoggingRepository
    {
        #region ---Constructor

        /// <summary>
        /// 初始化类型<see cref="LoggingRepository"/>的新实例
        /// </summary>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/15 10:53    创建
        /// </history>
        public LoggingRepository()
            : this(string.Empty)
        {
        }

        /// <summary>
        /// 初始化类型<see cref="LoggingRepository"/>的新实例
        /// </summary>
        /// <param name="name">日志存储器的名称</param>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/15 10:52    创建
        /// </history>
        public LoggingRepository(string name)
        {
            //保存参数
            this.m_Name = name;

            //创建根日志对象
            this.m_RootLogger = new RootLogger(this);
        }

        #endregion

        #region ---ILoggingRepository

        #region ---Property

        /// <summary>
        /// 获得或者设置日志存储器的名称
        /// </summary>
        /// <value>日志存储器的名称</value>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/15 10:49    创建
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/15 11:02    创建
        /// </history>
        public string Name
        {
            get
            {
                return this.m_Name;
            }
        }

        /// <summary>
        /// 获得或者设置默认的日志级别
        /// </summary>
        /// <value>默认的日志级别</value>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/15 10:42    创建
        /// </history>
        public Level DefaultLevel
        {
            get
            {
                return (null == this.m_DefaultLevel) ? Level.All : this.m_DefaultLevel;
            }
        }

        /// <summary>
        /// 获得当前存储器中注册的所有日志追加器
        /// </summary>
        /// <value>当前存储器中存储的所有日志追加器</value>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/13 13:51    创建
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/14 9:58    创建
        /// </history>
        public ILogAppender[] Appenders
        {
            get
            {
                //返回日志追加器
                return this.AppendersCache.Values.ToArray();
            }
        }

        /// <summary>
        /// 获得当前存储器中注册的所有日志记录器
        /// </summary>
        /// <value>当前存储器中注册的所有日志记录器</value>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/13 13:52    创建
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/14 9:58    创建
        /// </history>
        public ILogger[] Loggers
        {
            get
            {
                //返回日志记录器
                return this.LoggersCache.Values.ToArray();
            }
        }

        /// <summary>
        /// 获得默认的日志记录器
        /// </summary>
        /// <value>默认的日志记录器</value>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/13 13:57    创建
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/14 9:57    创建
        /// </history>
        public ILogger DefaultLogger
        {
            get
            {
                //获得默认的日志记录器
                return this.GetLogger(string.Empty);
            }
        }

        /// <summary>
        /// 获得日志级别映射表
        /// </summary>
        /// <value>日志级别映射表</value>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/16 15:40    创建
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/16 15:48    创建
        /// </history>
        public LevelMap LevelMap
        {
            get
            {
                return this.m_LevelMap;
            }
        }

        /// <summary>
        /// 获得一个值，该值用于判断当前日志存储器是否已经关闭
        /// </summary>
        /// <value>如果日志存储器已经关闭，则返回<c>true</c>，否则返回<c>false</c>。</value>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2010/1/6 11:02    创建
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2010/1/6 11:05    创建
        /// </history>
        public bool IsClosed
        {
            get
            {
                return this.m_IsClosed;
            }
        }

        #endregion

        #region ---Method

        /// <summary>
        /// 判断给定名称的日志记录器是否存在
        /// </summary>
        /// <param name="name">要判定的日志记录器的名称</param>
        /// <returns>
        /// 	<c>true</c>：给定名称的日志记录器存在<br/>
        /// 	<c>false</c>：给定名称的日志记录器不存在
        /// </returns>
        /// <remarks></remarks>
        /// <exception cref="ObjectDisposedException">当前日志存储器已经被关闭</exception>
        /// <exception cref="ArgumentNullException"><paramref name="name"/>为<c>null</c>引用或者为空字符串。</exception>
        /// <history>
        /// [zanezeng]               2009/10/13 13:58    创建
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/14 9:57    创建
        /// </history>
        public bool Exists(string name)
        {
            //断言参数
            ArgumentAssert.AssertStringArgumentNotNullOrEmpty(name, "name");

            //断言没有被处置
            this.AssertNotDisposed();

            //判断是否存在
            return this.LoggersCache.ContainsKey(name);
        }

        /// <summary>
        /// 获得给定名称的日志记录器
        /// </summary>
        /// <param name="name">要获得的日志记录器的名称</param>
        /// <returns>
        /// 给定名称的日志记录器，如果给定名称的日志记录器不存在，则尝试返回上一级名称的日志记录器，如果根名称的日志记录器也不存在，则返回默认的日志记录器
        /// </returns>
        /// <remarks></remarks>
        /// <exception cref="ObjectDisposedException">当前日志存储器已经被关闭</exception>
        /// <exception cref="ArgumentNullException"><paramref name="name"/>为<c>null</c>引用或者为空字符串。</exception>
        /// <history>
        /// [zanezeng]               2009/10/13 13:56    创建
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/14 9:57    创建
        /// </history>
        public ILogger GetLogger(string name)
        {
            //断言参数
            ArgumentAssert.AssertStringArgumentNotNullOrEmpty(name, "name");

            //断言没有被处置
            this.AssertNotDisposed();

            //获得日志记录器
            return this.GetLoggerInternal(name);
        }

        /// <summary>
        /// 获得给定名称的日志追加器
        /// </summary>
        /// <param name="name">要获得的日志追加器的名称</param>
        /// <returns>
        /// 给定名称的日志追加器，如果给定名称的日志追加器不存在，则返回<c>null</c>引用。
        /// </returns>
        /// <remarks></remarks>
        /// <exception cref="ObjectDisposedException">当前日志存储器已经被关闭</exception>
        /// <exception cref="ArgumentNullException"><paramref name="name"/>为<c>null</c>引用或者为空字符串。</exception>
        /// <history>
        /// [zanezeng]               2009/10/13 14:00    创建
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/14 9:57    创建
        /// </history>
        public ILogAppender GetAppender(string name)
        {
            //断言没有被处置
            this.AssertNotDisposed();

            //用于保存日志追加器
            ILogAppender appender = null;

            //在日志追加器缓存中检索
            if (!this.AppendersCache.TryGetValue(name, out appender))
            {
                //设置为空引用
                appender = null;
            }

            //返回检索到的日志追加器
            return appender;
        }

        /// <summary>
        /// 将给定的日志条目写入到日志记录器中
        /// </summary>
        /// <param name="entry">要写入的日志条目</param>
        /// <remarks></remarks>
        /// <exception cref="ObjectDisposedException">当前日志存储器已经被关闭</exception>
        /// <history>
        /// [zanezeng]               2009/10/14 11:55    创建
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/14 12:09    创建
        /// </history>
        public void WriteLog(LogEntry entry)
        {
            //断言没有被处置
            this.AssertNotDisposed();

            //转调
            this.GetLogger(entry.LoggerName).WriteLog(entry);
        }

        /// <summary>
        /// 获得一个值，该值用于判断给定名称的日志记录器是否允许输出给定级别的日志
        /// </summary>
        /// <param name="name">日志记录器的名称</param>
        /// <param name="level">要判定的日志级别</param>
        /// <returns>
        /// 	<c>true</c>：允许输出<br/>
        /// 	<c>false</c>：不允许输出
        /// </returns>
        /// <exception cref="ArgumentNullException"><paramref name="name"/>为<c>null</c>引用或者为空字符串。</exception>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/14 12:07    创建
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/14 12:09    创建
        /// </history>
        public bool IsLevelEnabled(string name, Level level)
        {
            //判断日志存储器是否已经被关闭
            if (this.m_IsClosed)
            {
                //如果日志存储器已经被关闭，则总是返回不允许
                return false;
            }

            //转调
            return this.GetLogger(name).IsLevelEnabled(level);
        }

        /// <summary>
        /// 关闭当前日志存储器
        /// </summary>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2010/1/6 11:03    创建
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2010/1/6 11:07    创建
        /// </history>
        public void Close()
        {
            //处置日志存储器
            this.Dispose();
        }

        #endregion

        #region ---Event

        /// <summary>
        /// 配置重置事件
        /// </summary>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/16 10:38    创建
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/16 10:39    创建
        /// </history>
        public event EventHandler ConfigurationReset
        {
            add
            {
                this.m_Events.AddHandler(KEY_CONFIGURATIONRESET, value);
            }
            remove
            {
                this.m_Events.RemoveHandler(KEY_CONFIGURATIONRESET, value);
            }
        }

        /// <summary>
        /// 配置发生变化事件
        /// </summary>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/16 10:38    创建
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/16 10:39    创建
        /// </history>
        public event EventHandler ConfigurationChanged
        {
            add
            {
                this.m_Events.AddHandler(KEY_CONFIGURATIONCHANGED, value);
            }
            remove
            {
                this.m_Events.RemoveHandler(KEY_CONFIGURATIONCHANGED, value);
            }
        }

        /// <summary>
        /// 日志存储器被关闭事件
        /// </summary>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2010/1/6 11:04    创建
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2010/1/6 11:06    创建
        /// </history>
        public event EventHandler Closed
        {
            add
            {
                this.m_Events.AddHandler(KEY_CLOSED, value);
            }
            remove
            {
                this.m_Events.RemoveHandler(KEY_CLOSED, value);
            }
        }

        #endregion

        #endregion

        #region ---IConfigurableLoggingRepository

        /// <summary>
        /// 获得或者设置默认的日志记录器的名称
        /// </summary>
        /// <value>默认的日志记录器的名称</value>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/15 11:34    创建
        /// </history>
        public string DefaultLoggerName
        {
            get
            {
                return this.m_DefaultLoggerName;
            }
            set
            {
                this.m_DefaultLoggerName = (null == value) ? string.Empty : value;
            }
        }

        /// <summary>
        /// 使用给定的配置信息配置当前日志存储器
        /// </summary>
        /// <param name="configuration">用来配置日志存储器的配置信息</param>
        /// <param name="handlerFactory">配置节点处理器工厂</param>
        /// <param name="variableProvider">扩展变量提供者</param>
        /// <remarks></remarks>
        /// <exception cref="ObjectDisposedException">当前日志存储器已经被关闭</exception>
        /// <exception cref="ArgumentNullException"><paramref name="configuration"/>为<c>null</c>引用。</exception>
        /// <exception cref="ArgumentNullException"><paramref name="handlerFactory"/>为<c>null</c>引用。</exception>
        /// <exception cref="ArgumentNullException"><paramref name="variableProvider"/>为<c>null</c>引用。</exception>
        /// <history>
        /// [zanezeng]               2009/10/14 9:44    创建
        /// </history>
        /// <remarks></remarks>
        /// <exception cref="ArgumentNullException"><paramref name="configuration"/>为<c>null</c>引用。</exception>
        /// <history>
        /// [zanezeng]               2009/10/14 9:48    创建
        /// </history>
        public void Configure(IConfiguration configuration,
                               IConfigurationNodeHandlerFactory<ParseContext> handlerFactory,
                               IExtendedVariableProvider variableProvider)
        {
            //断言没有被处置
            this.AssertNotDisposed();

            //断言参数
            ArgumentAssert.AssertArgumentNotNull(configuration, "configuration");
            ArgumentAssert.AssertArgumentNotNull(handlerFactory, "handlerFactory");
            ArgumentAssert.AssertArgumentNotNull(variableProvider, "variableProvider");

            //创建解析上下文
            ParseContext context = new ParseContext(this, handlerFactory, variableProvider);

            //配置当前日志存储器
            this.ConfigRepository(configuration, context);

            //通知配置变化事件
            this.OnConfigurationChanged();
        }

        /// <summary>
        /// 将给定的日志追加器注册当前日志存储器中
        /// </summary>
        /// <param name="appender">要注册的日志追加器</param>
        /// <remarks>如果同名的日志追加器已经存在，则替换已经存在的日志追加器。</remarks>
        /// <exception cref="ArgumentNullException"><paramref name="appender"/>为<c>null</c>引用。</exception>
        /// <exception cref="ArgumentException"><paramref name="appender"/>的<see cref="ILogAppender.Name"/>为空字符串或者为<c>null</c>引用。</exception>
        /// <exception cref="ObjectDisposedException">当前日志存储器已经被关闭。</exception>
        /// <history>
        /// [zanezeng]               2009/10/15 9:33    创建
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2010/11/24 14:32    创建
        /// </history>
        public void RegisterAppender(ILogAppender appender)
        {
            //断言参数
            ArgumentAssert.AssertArgumentNotNull(appender, "appender");

            //判断日志追加器的名称是否有效
            if (string.IsNullOrEmpty(appender.Name))
            {
                //抛出异常
                throw new ArgumentException("appender");
            }

            //断言没有被处置
            this.AssertNotDisposed();

            //用于保存同名的日志追加器
            ILogAppender existedAppender = null;

            //同步
            lock (this.SyncRoot)
            {
                //检索同名的日志追加器
                if (this.m_Appenders.TryGetValue(appender.Name, out existedAppender) && object.ReferenceEquals(existedAppender, appender))
                {
                    //如果是同一个日志追加器，则直接返回
                    return;
                }

                //从日志追加器列表中删除已经存在的日志追加器
                this.m_Appenders.Remove(appender.Name);

                //输出日志
                if (LoggingContext.MetaLog.IsTraceEnabled)
                {
                    LoggingContext.MetaLog.Trace("从日志存储器'{0}'中删除日志追加器'{1}'", this.Name, existedAppender);
                }

                //将要注册的日志追加器添加到日志追加器列表中
                this.m_Appenders.Add(appender.Name, appender);

                //输出日志
                if (LoggingContext.MetaLog.IsTraceEnabled)
                {
                    LoggingContext.MetaLog.Trace("向日志存储器'{0}'中注册日志追加器'{1}'", this.Name, appender);
                }

                //清除日志追加器缓存
                this.m_AppendersCache = null;
            }

            //触发配置变化事件
            this.OnConfigurationChanged();

            //判断是否需要销毁被注销的日志追加器
            if (null != existedAppender)
            {
                //销毁被注销的日志追加器
                existedAppender.Dispose();
            }
        }

        /// <summary>
        /// 从当前的日志存储器中注销给定的日志追加器
        /// </summary>
        /// <param name="appender">要注销的日志追加器</param>
        /// <returns>
        /// 	<c>true</c>：给定的日志追加器注销成功<br/>
        /// 	<c>false</c>：给定的日志追加器注销失败
        /// </returns>
        /// <exception cref="ArgumentNullException"><paramref name="appender"/>为<c>null</c>引用。</exception>
        /// <exception cref="ArgumentException"><paramref name="appender"/>的<see cref="ILogAppender.Name"/>为空字符串或者为<c>null</c>引用。</exception>
        /// <exception cref="ObjectDisposedException">当前日志存储器已经被关闭</exception>
        /// <remarks>注意：名称不区分大小写</remarks>
        /// <history>
        /// [zanezeng]               2009/10/15 9:40    创建
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2010/11/24 14:35    创建
        /// </history>
        public bool UnregisterAppender(ILogAppender appender)
        {
            //断言参数
            ArgumentAssert.AssertArgumentNotNull(appender, "appender");

            //判断日志追加器的名称是否有效
            if (string.IsNullOrEmpty(appender.Name))
            {
                //抛出异常
                throw new ArgumentException("appender");
            }

            //断言没有被处置
            this.AssertNotDisposed();

            //用于保存是否删除
            bool isRemoved = false;

            //同步
            lock (this.SyncRoot)
            {
                //用于保存同名的日志追加器
                ILogAppender existedAppender = null;

                //检索同名的日志追加器
                if (this.m_Appenders.TryGetValue(appender.Name, out existedAppender) && object.ReferenceEquals(existedAppender, appender))
                {
                    //如果是同一个日志追加器，则直接删除
                    isRemoved = this.m_Appenders.Remove(appender.Name);

                    //判断是否成功删除
                    if (isRemoved)
                    {
                        //输出日志
                        if (LoggingContext.MetaLog.IsTraceEnabled)
                        {
                            LoggingContext.MetaLog.Trace("从日志存储器'{0}'中删除日志追加器'{1}'", this.Name, appender.Name);
                        }

                        //清除日志存储器缓存
                        this.m_AppendersCache = null;
                    }
                }
            }

            //判断是否成功删除
            if (isRemoved)
            {
                //触发配置变化事件
                this.OnConfigurationChanged();
            }

            //返回是否成功删除
            return isRemoved;
        }

        /// <summary>
        /// 从当前的日志存储器中注销给定名称的日志追加器
        /// </summary>
        /// <param name="name">要注销日志追加器的注册名称</param>
        /// <returns>
        /// 被注销的日志追加器实例，如果给定名称的日志追加器不存在，则返回<c>null</c>引用。
        /// </returns>
        /// <exception cref="ArgumentNullException"><paramref name="name"/>为空字符串或者为<c>null</c>引用。</exception>
        /// <exception cref="ObjectDisposedException">当前日志存储器已经被关闭</exception>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/15 9:44    创建
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2010/11/24 14:40    创建
        /// </history>
        public ILogAppender UnregisterAppender(string name)
        {
            //断言参数
            ArgumentAssert.AssertStringArgumentNotNullOrEmpty(name, "name");

            //断言没有被处置
            this.AssertNotDisposed();

            //用于保存注销的日志追加器
            ILogAppender appender = null;

            //同步
            lock (this.SyncRoot)
            {
                //判断给定名称的日志追加器是否存在
                if (this.m_Appenders.TryGetValue(name, out appender))
                {
                    //从日志追加器列表中删除
                    if (this.m_Appenders.Remove(name))
                    {
                        //循环所有的日志记录器，从日志记录器中删除日志追加器
                        foreach (Logger existedLogger in this.m_Loggers.Values)
                        {
                            //从现有的日志记录器中删除日志追加器
                            existedLogger.RemoveAppender(appender);
                        }

                        //输出日志
                        if (LoggingContext.MetaLog.IsTraceEnabled)
                        {
                            LoggingContext.MetaLog.Trace("从日志存储器'{0}'中删除日志追加器'{1}'", this.Name, name);
                        }

                        //清除日志存储器缓存
                        this.m_AppendersCache = null;

                        //触发配置变化事件
                        this.OnConfigurationChanged();
                    }
                }
            }

            //返回注销的日志追加器
            return appender;
        }

        /// <summary>
        /// 注册日志记录器
        /// </summary>
        /// <param name="name">要注册的日志记录器的名称</param>
        /// <param name="level">日志记录器允许输出的最低日志级别，如果为NULL，则默认为日志存储器的默认日志级别</param>
        /// <param name="isDefault">是否设置为默认日志记录器</param>
        /// <param name="referAppenders">要注册的日志记录器引用的日志追加器</param>
        /// <remarks></remarks>
        /// <exception cref="ObjectDisposedException">当前日志存储器已经被关闭</exception>
        /// <exception cref="ArgumentNullException"><paramref name="name"/>为Null或者为空字符串</exception>
        /// <exception cref="ArgumentException"><paramref name="referAppenders"/>引用不存在的日志追加器</exception>
        /// <history>
        /// [zanezeng]               2009/10/15 9:49    创建
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/15 10:37    创建
        /// </history>
        public void RegisterLogger(string name, Level level, bool isDefault, params string[] referAppenders)
        {
            //断言没有被处置
            this.AssertNotDisposed();

            //断言参数
            ArgumentAssert.AssertStringArgumentNotNullOrEmpty(name, "name");

            //注册日志记录器
            this.RegisterLoggerInternal(name, level, referAppenders, true);

            //判断是否为默认日志记录器
            if (isDefault)
            {
                //如果是，则设置默认日志记录器
                this.DefaultLoggerName = name;
            }
        }

        /// <summary>
        /// 注销给定名称的日志记录器
        /// </summary>
        /// <param name="name">要注销的日志记录器的名称</param>
        /// <returns>
        /// 	<c>true</c>：给定名称的日志记录器注销成功<br/>
        /// 	<c>false</c>：给定名称的日志记录器不存在
        /// </returns>
        /// <exception cref="ArgumentNullException"><paramref name="name"/>为空字符串或者为<c>null</c>引用。</exception>
        /// <exception cref="ObjectDisposedException">当前日志存储器已经被关闭</exception>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/15 9:50    创建
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2010/11/24 15:27    创建
        /// </history>
        public bool UnregisterLogger(string name)
        {
            //断言参数
            ArgumentAssert.AssertStringArgumentNotNullOrEmpty(name, "name");

            //断言没有被处置
            this.AssertNotDisposed();

            //判断名称是否为Null或者为空白字符串
            if (string.IsNullOrEmpty(name))
            {
                //如果名称是否为Null或者为空白字符串，认为注销失败
                return false;
            }

            //用于记录是否成功删除
            bool isRemoved = false;

            //同步
            lock (this.SyncRoot)
            {
                //删除日志记录器
                isRemoved = this.m_Loggers.Remove(name);
            }

            //判断是否删除成功
            if (isRemoved)
            {
                //输出日志
                if (LoggingContext.MetaLog.IsTraceEnabled)
                {
                    LoggingContext.MetaLog.Trace("从日志存储器'{0}'中注销日志记录器'{1}'", this.Name, name);
                }

                //清除日志记录器缓存
                this.m_LoggersCache = null;

                //触发配置变化事件
                this.OnConfigurationChanged();
            }

            //返回是否删除成功
            return isRemoved;
        }

        /// <summary>
        /// 设置当前日志存储器的默认日志级别
        /// </summary>
        /// <param name="level">默认的日志级别</param>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/16 9:51    创建
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/16 9:52    创建
        /// </history>
        public void SetDefaultLevel(Level level)
        {
            this.m_DefaultLevel = level;
        }

        /// <summary>
        /// 设置当前日志存储器的名称
        /// </summary>
        /// <param name="name">日志存储器的名称</param>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/16 9:58    创建
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/16 9:59    创建
        /// </history>
        public void SetName(string name)
        {
            this.m_Name = name;
        }

        #endregion

        #region ---IDisposable

        /// <summary>
        /// 执行与释放或重置非托管资源相关的应用程序定义的任务
        /// </summary>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/19 12:06    创建
        /// </history>
        public void Dispose()
        {
            //判断是否已经被关闭
            if (this.m_IsClosed)
            {
                //如果已经关闭，则直接返回
                return;
            }

            //设置已经被关闭
            this.m_IsClosed = true;

            //释放托管资源
            this.Dispose(true);

            //触发关闭事件
            this.OnClosed();

            //阻止回收
            GC.SuppressFinalize(this);
        }

        #endregion

        #region ---Public Method

        /// <summary>
        /// 返回表示当前<see cref="LoggingRepository"/>对象的<see cref="String"/>对象
        /// </summary>
        /// <returns>
        /// 表示当前<see cref="LoggingRepository"/>对象的<see cref="String"/>对象
        /// </returns>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/16 11:22    创建
        /// </history>
        public override string ToString()
        {
            return string.Format("Repository:{0}", this.m_Name);
        }

        /// <summary>
        /// 使用给定的配置信息配置当前日志存储器
        /// </summary>
        /// <param name="configuration">用来配置日志存储器的配置信息</param>
        /// <remarks></remarks>
        /// <exception cref="ObjectDisposedException">当前日志存储器已经被关闭</exception>
        /// <history>
        /// [zanezeng]               2009/10/14 9:44    创建
        /// </history>
        /// <remarks></remarks>
        /// <exception cref="ArgumentNullException"><paramref name="configuration"/>为<c>null</c>引用。</exception>
        /// <history>
        /// [zanezeng]               2009/10/14 9:48    创建
        /// </history>
        public void Configure(IConfiguration configuration)
        {
            //转调
            this.Configure(configuration, NodeHandlerRegistry.Default, DefaultExtendedVariableProvider.Default);
        }

        #endregion

        #region ---Protected Method

        /// <summary>
        /// 获得给定名称日志记录器的适配器
        /// </summary>
        /// <param name="name">要获得的日志记录器的名称</param>
        /// <returns>给定名称日志记录器的适配器</returns>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/14 13:54    创建
        /// </history>
        protected ILogger GetLoggerInternal(string name)
        {
            //获得所有的日志
            Dictionary<string, AbstractLogger> loggers = this.LoggersCache;

            //判断是否有日志记录器
            if (0 == loggers.Count)
            {
                //如果没有日志记录器，则直接返回根日志记录器
                return this.m_RootLogger;
            }

            //用于记录是否获得默认的日志记录器
            bool isGetDefaultLogger = false;

            //判断要获得的日志记录器的名称是否为NULL或者为空字符串
            if (string.IsNullOrEmpty(name))
            {
                //如果日志记录器的名称为NULL或者为空字符串，则设置为默认日志名称
                name = this.DefaultLoggerName;

                //设置为获取默认的日志记录器
                isGetDefaultLogger = true;
            }

            //判断日志名称是否为NULL或者为空字符串
            if (string.IsNullOrEmpty(name))
            {
                //直接返回根日志对象
                return this.m_RootLogger;
            }
            //判断是否尝试获得默认的日志记录器
            else if (0 == string.Compare(name, this.DefaultLoggerName, StringComparison.InvariantCulture))
            {
                //设置为获取默认的日志记录器
                isGetDefaultLogger = true;
            }

            //用于保存日志记录器
            AbstractLogger namedLogger = null;

            //用于保存上一级日志记录器的名称
            string parentLoggerName = name;

            //循环获得日志记录器
            while (null != parentLoggerName)
            {
                //获得日志追加器
                if (loggers.TryGetValue(parentLoggerName, out namedLogger))
                {
                    //返回日志追加器
                    return namedLogger;
                }

                //获得上一级的日志记录器名称
                parentLoggerName = GetParentLoggerName(parentLoggerName);
            }

            //判断是否获得默认的日志记录器
            if (isGetDefaultLogger)
            {
                //如果是活的默认的日志记录器，则直接返回根日志记录器
                return this.m_RootLogger;
            }

            //默认返回默认日志记录器
            return this.GetLoggerInternal(this.DefaultLoggerName);
        }

        /// <summary>
        /// 注册日志记录器
        /// </summary>
        /// <param name="name">要注册的日志记录器的名称</param>
        /// <param name="level">日志记录器允许输出的最低日志级别，如果为NULL，则默认为日志存储器的默认日志级别</param>
        /// <param name="referAppenders">要注册的日志记录器引用的日志追加器</param>
        /// <param name="throwOnError">在发生错误时是否跑出异常，如果设置为<c>True</c>则抛出异常，否则不抛出异常</param>
        /// <remarks></remarks>
        /// <exception cref="ArgumentNullException"><paramref name="name"/>为Null或者为空字符串</exception>
        /// <exception cref="ArgumentException"><paramref name="referAppenders"/>引用不存在的日志追加器</exception>
        /// <history>
        /// [zanezeng]               2009/10/15 9:49    创建
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/15 10:37    创建
        /// </history>
        protected void RegisterLoggerInternal(string name, Level level, string[] referAppenders, bool throwOnError)
        {
            //断言参数
            ArgumentAssert.AssertStringArgumentNotNullOrEmpty(name, "name");

            //判断日志级别是否为NULL
            if (null == level)
            {
                //如果日志级别为NULL，则设置为默认日志级别
                level = this.DefaultLevel;
            }

            //创建日志记录器
            AbstractLogger logger = this.LoggerFactory.CreateLogger(name, level, this);

            //用于保存日志追加器
            ILogAppender appender = null;

            //循环添加日志追加器
            foreach (string appenderName in referAppenders)
            {
                //判断引用追加器的名称是否为NULL或者为空字符串
                if (string.IsNullOrEmpty(appenderName))
                {
                    //输出日志
                    if (LoggingContext.MetaLog.IsWarnEnabled)
                    {
                        LoggingContext.MetaLog.Warn("日志记录器'{0}'使用空白字符串来引用日志存储器'{1}'中的日志追加器", name, this.Name);
                    }

                    //如果引用追加器的名称是否为空引用或者为空字符串，则忽略
                    continue;
                }

                //获得日志追加器
                appender = this.GetAppender(appenderName);

                //判断日志追加器是否存在
                if (null == appender)
                {
                    //输出日志
                    if (LoggingContext.MetaLog.IsErrorEnabled)
                    {
                        LoggingContext.MetaLog.Error("无法在日志存储器'{0}'中找到日志记录器'{1}'引用的日志追加器'{2}'", this.Name, name, appenderName);
                    }

                    //判断是否抛出异常
                    if (throwOnError)
                    {
                        //抛出异常
                        throw new ArgumentException(string.Format(Properties.Resources.MSG_APPENDER_NOT_FOUND, appenderName, this.Name));
                    }
                }

                //附加日志记录器的适配器
                logger.AddAppender(new AppenderAdapter(appenderName, appender, this));
            }

            //输出日志
            if (LoggingContext.MetaLog.IsTraceEnabled)
            {
                LoggingContext.MetaLog.Trace("开始向日志存储器'{0}'中注册日志记录器'{1}'", this.Name, name);
            }

            //同步
            lock (this.SyncRoot)
            {
                //注册日志记录器
                this.m_Loggers[name] = logger;
            }

            //清除日志记录器缓存
            this.m_LoggersCache = null;

            //输出日志
            if (LoggingContext.MetaLog.IsTraceEnabled)
            {
                LoggingContext.MetaLog.Trace("结束向日志存储器'{0}'中注册日志记录器'{1}'", this.Name, name);
            }

            //触发配置变化事件
            this.OnConfigurationChanged();
        }

        /// <summary>
        /// 重置当前日志存储器
        /// </summary>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/15 11:32    创建
        /// </history>
        protected virtual void Reset()
        {
            //用于保存日志记录器
            ILogger[] loggers = null;

            //用于保存日志追加器
            ILogAppender[] appenders = null;

            //同步
            lock (this.SyncRoot)
            {
                //获得日志记录器
                loggers = this.Loggers;

                //获得日志追加器
                appenders = this.Appenders;

                //清除所有的日志记录器
                this.m_Loggers.Clear();

                //清除所有的日志追加器
                this.m_Appenders.Clear();

                //请出日志记录器缓存
                this.m_LoggersCache = null;

                //清除日志追加器缓存
                this.m_AppendersCache = null;
            }

            //循环关闭所有的日志记录器
            if (null != loggers)
            {
                foreach (ILogger logger in loggers)
                {
                    //关闭日志记录器
                    logger.Close();
                }
            }

            //循环关闭所有的日志追加器
            if (null != appenders)
            {
                foreach (ILogAppender appender in this.m_Appenders.Values)
                {
                    //关闭日志追加器
                    appender.Dispose();
                }
            }

            //重置默认的日志名称
            this.m_DefaultLoggerName = string.Empty;

            //重置默认的日志级别
            this.m_DefaultLevel = Level.All;

            //触发配置重置事件
            this.OnConfigurationReset();
        }

        /// <summary>
        /// 触发配置变化事件
        /// </summary>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/16 10:43    创建
        /// </history>
        protected void OnConfigurationChanged()
        {
            //判断是否正在配置
            if (!this.m_IsConfiguring)
            {
                //获得事件委托
                EventHandler handler = (EventHandler)this.m_Events[KEY_CONFIGURATIONCHANGED];

                //判断是否有事件委托
                if (null != handler)
                {
                    //输出日志
                    if (LoggingContext.MetaLog.IsTraceEnabled)
                    {
                        LoggingContext.MetaLog.Trace("日志存储器'{0}'发生变化，触发ConfigurationChanged事件", this.Name);
                    }

                    //触发事件
                    handler(this, EventArgs.Empty);
                }
            }
        }

        /// <summary>
        /// 触发配置重置事件
        /// </summary>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/16 10:45    创建
        /// </history>
        protected void OnConfigurationReset()
        {
            //获得事件委托
            EventHandler handler = (EventHandler)this.m_Events[KEY_CONFIGURATIONRESET];

            //判断是否有事件委托
            if (null != handler)
            {
                //输出日志
                if (LoggingContext.MetaLog.IsTraceEnabled)
                {
                    LoggingContext.MetaLog.Trace("日志存储器'{0}'发生重置，触发ConfigurationReset事件", this.Name);
                }

                //触发事件
                handler(this, EventArgs.Empty);
            }
        }

        /// <summary>
        /// 触发关闭事件
        /// </summary>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2010/1/6 13:17    创建
        /// </history>
        protected void OnClosed()
        {
            //获得事件委托
            EventHandler handler = (EventHandler)this.m_Events[KEY_CLOSED];

            //判断是否有事件委托
            if (null != handler)
            {
                //输出日志
                if (LoggingContext.MetaLog.IsTraceEnabled)
                {
                    LoggingContext.MetaLog.Trace("关闭日志存储器'{0}'，触发Closed事件", this.Name);
                }

                //触发事件
                handler(this, EventArgs.Empty);
            }
        }

        /// <summary>
        /// 执行与释放或重置非托管资源相关的应用程序定义的任务
        /// </summary>
        /// <param name="disposing">是否释放非托管资源</param>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/19 12:06    创建
        /// </history>
        protected virtual void Dispose(bool disposing)
        {
            //重置日志存储器
            this.Reset();
        }

        #endregion

        #region ---Private Method

        /// <summary>
        /// 获得给定日志记录器名称的上一级日志记录器的名称
        /// </summary>
        /// <param name="loggerName">要获得上一级日志记录器名称的日志记录器名称</param>
        /// <returns>上一级日志记录器的名称，如果不存在上一级日志记录器，则返回<c>null</c>引用。</returns>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/15 17:37    创建
        /// </history>
        private static string GetParentLoggerName(string loggerName)
        {
            //获得分隔符的位置
            int index = loggerName.LastIndexOf(SEPARATOR_LOGGERNAME);

            //判断是否有分隔符
            if (-1 == index)
            {
                //如果没有分割符，则返回NULL
                return null;
            }

            //获得上一级日志记录器的名称
            return loggerName.Substring(0, index);
        }

        /// <summary>
        /// 使用给定的配置对象配置当前日志存储器
        /// </summary>
        /// <param name="configuration">用于配置当前日志存储器的配置对象</param>
        /// <param name="context">解析上下文</param>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/12/15 17:28    创建
        /// </history>
        private void ConfigRepository(IConfiguration configuration, ParseContext context)
        {
            //同步
            lock (this.SyncRoot)
            {
                try
                {
                    //设置正在配置
                    this.m_IsConfiguring = true;

                    //输出日志
                    if (LoggingContext.MetaLog.IsTraceEnabled)
                    {
                        LoggingContext.MetaLog.Trace("开始重置日志存储器'{0}'", this.Name);
                    }

                    //重置日志存储器
                    this.Reset();

                    //输出日志
                    if (LoggingContext.MetaLog.IsTraceEnabled)
                    {
                        LoggingContext.MetaLog.Trace("日志存储器'{0}'重置完毕", this.Name);
                    }

                    //输出日志
                    if (LoggingContext.MetaLog.IsTraceEnabled)
                    {
                        LoggingContext.MetaLog.Trace("开始配置日志存储器'{0}'", this.Name);
                    }

                    //用于保存配置节点处理器
                    IConfigurationNodeHandler<ParseContext> handler;

                    //循环当前配置的所有子节点
                    foreach (IConfigurationNode node in configuration.ChildNodes)
                    {
                        //获得配置节点处理器
                        handler = context.GetNodeHandler(node);

                        //判断是否为Null
                        if (null == handler)
                        {
                            //抛出异常
                            throw new NotSupportedException(string.Format(Properties.Resources.MSG_TAG_NOTSUPPORTED, node.Name));
                        }

                        //处理节点
                        handler.Porcess(node, context);
                    }

                    //输出日志
                    if (LoggingContext.MetaLog.IsTraceEnabled)
                    {
                        LoggingContext.MetaLog.Trace("日志存储器'{0}'配置完毕", this.Name);
                    }
                }
                finally
                {
                    //设置配置完成
                    this.m_IsConfiguring = false;
                }
            }
        }

        /// <summary>
        /// 断言对象没有被处置
        /// </summary>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]   2008-12-7 19:42    Created
        /// </history>
        private void AssertNotDisposed()
        {
            //判断是否已经被处置
            if (this.m_IsClosed)
            {
                //抛出异常
                throw new ObjectDisposedException(Properties.Resources.MSG_REPOSITORY_CLOSED);
            }
        }

        #endregion

        #region ---Proeprty

        /// <summary>
        /// 获得日志记录器工厂
        /// </summary>
        /// <value>日志记录器工厂</value>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/19 11:39    创建
        /// </history>
        public ILoggerFactory LoggerFactory
        {
            get
            {
                return (null == this.m_LoggerFactory) ? AsyncLoggerFactory.Default : this.m_LoggerFactory;
            }
            set
            {
                this.m_LoggerFactory = value;
            }
        }

        /// <summary>
        /// 获得同步对象。
        /// </summary>
        /// <value>同步对象。</value>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2010/11/24 13:56    创建
        /// </history>
        protected object SyncRoot
        {
            get
            {
                return this.m_SyncRoot;
            }
        }

        /// <summary>
        /// 获得日志追加器缓存。
        /// </summary>
        /// <value>日志追加器缓存。</value>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2010/11/24 14:05    创建
        /// </history>
        protected Dictionary<string, ILogAppender> AppendersCache
        {
            get
            {
                //判断日志追加器缓存是否有效
                if (null != this.m_AppendersCache)
                {
                    //直接返回缓存
                    return this.m_AppendersCache;
                }

                //同步
                lock (this.SyncRoot)
                {
                    //判断日志追加器缓存是否有效
                    if (null != this.m_AppendersCache)
                    {
                        //直接返回缓存
                        return this.m_AppendersCache;
                    }

                    //更新日志追加器缓存
                    this.m_AppendersCache = new Dictionary<string, ILogAppender>(this.m_Appenders, StringComparer.InvariantCulture);
                }

                //返回缓存
                return this.m_AppendersCache;
            }
        }

        /// <summary>
        /// 获得日志记录器缓存。
        /// </summary>
        /// <value>日志记录器缓存。</value>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2010/11/24 14:07    创建
        /// </history>
        protected Dictionary<string, AbstractLogger> LoggersCache
        {
            get
            {
                //判断缓存是否有效
                if (null != this.m_LoggersCache)
                {
                    //直接返回缓存
                    return this.m_LoggersCache;
                }

                //同步
                lock (this.SyncRoot)
                {
                    //判断缓存是否有效
                    if (null != this.m_LoggersCache)
                    {
                        //直接返回缓存
                        return this.m_LoggersCache;
                    }

                    //更新缓存
                    this.m_LoggersCache = new Dictionary<string, AbstractLogger>(this.m_Loggers, StringComparer.InvariantCulture);
                }

                //返回缓存
                return this.m_LoggersCache;
            }
        }

        #endregion

        #region ---Field

        /// <summary>
        /// 事件列表
        /// </summary>
        private EventHandlerList m_Events = new EventHandlerList();

        /// <summary>
        /// 日志存储器的名称
        /// </summary>
        private string m_Name;

        /// <summary>
        /// 是否正在配置
        /// </summary>
        private volatile bool m_IsConfiguring;

        /// <summary>
        /// 根日志对象
        /// </summary>
        private RootLogger m_RootLogger;

        /// <summary>
        /// 日志追加器缓存
        /// </summary>
        private volatile Dictionary<string, ILogAppender> m_AppendersCache;

        /// <summary>
        /// 日志记录器缓存
        /// </summary>
        private volatile Dictionary<string, AbstractLogger> m_LoggersCache;

        /// <summary>
        /// 默认的日志记录器名称
        /// </summary>
        private string m_DefaultLoggerName = string.Empty;

        /// <summary>
        /// 日志记录器字典
        /// </summary>
        private Dictionary<string, AbstractLogger> m_Loggers = new Dictionary<string, AbstractLogger>(StringComparer.InvariantCulture);

        /// <summary>
        /// 日志追加器字典
        /// </summary>
        private Dictionary<string, ILogAppender> m_Appenders = new Dictionary<string, ILogAppender>(StringComparer.InvariantCulture);

        /// <summary>
        /// 默认的日志级别
        /// </summary>
        private Level m_DefaultLevel;

        /// <summary>
        /// 日志级别映射表
        /// </summary>
        private LevelMap m_LevelMap = new LevelMap(LoggingContext.DefaultLevelMap, false);

        /// <summary>
        /// 日志记录器名称的层级分隔符
        /// </summary>
        private const char SEPARATOR_LOGGERNAME = '.';

        /// <summary>
        /// 日志记录器工厂
        /// </summary>
        private ILoggerFactory m_LoggerFactory;

        /// <summary>
        /// 用于记录日志存储器是否已经被关闭
        /// </summary>
        private bool m_IsClosed;

        /// <summary>
        /// 同步对象
        /// </summary>
        private object m_SyncRoot = new object();

        #endregion

        #region ---Const

        /// <summary>
        /// 配置重置事件键
        /// </summary>
        private static readonly object KEY_CONFIGURATIONRESET = new object();

        /// <summary>
        /// 配置变化事件键
        /// </summary>
        private static readonly object KEY_CONFIGURATIONCHANGED = new object();

        /// <summary>
        /// 日志存储器关闭事件键
        /// </summary>
        private static readonly object KEY_CLOSED = new object();

        #endregion
    }
}
